import {
  BarChart,
  BarSeriesOption,
  GaugeChart,
  GaugeSeriesOption,
  HeatmapChart,
  HeatmapSeriesOption,
  LineChart,
  LineSeriesOption,
  PieChart,
  PieSeriesOption,
  TreemapChart,
  TreemapSeriesOption,
} from 'echarts/charts';
import {
  DatasetComponent,
  DatasetComponentOption,
  DataZoomComponent,
  DataZoomComponentOption,
  GraphicComponent,
  GridComponent,
  GridComponentOption,
  LegendComponent,
  LegendComponentOption,
  TitleComponent,
  TitleComponentOption,
  ToolboxComponent,
  ToolboxComponentOption,
  TooltipComponent,
  TooltipComponentOption,
  VisualMapComponent,
} from 'echarts/components';
import * as echarts from 'echarts/core';
import { EChartsType } from 'echarts/core';
import { UniversalTransition } from 'echarts/features';
import { SVGRenderer } from 'echarts/renderers';
import { ECElementEvent } from 'echarts/types/src/util/types';
import React, {
  ForwardedRef,
  useEffect,
  useImperativeHandle,
  useLayoutEffect,
  useRef,
} from 'react';
// 注册echarts的组件和功能
echarts.use([
  GraphicComponent,
  VisualMapComponent,
  DatasetComponent,
  DataZoomComponent,
  GridComponent,
  LegendComponent,
  TitleComponent,
  ToolboxComponent,
  TooltipComponent,
  LineChart,
  BarChart,
  PieChart,
  TreemapChart,
  UniversalTransition,
  SVGRenderer,
  GaugeChart,
  HeatmapChart,
]);
// 定义图表的配置项类型
export type MyChartOption = echarts.ComposeOption<
  | DatasetComponentOption
  | DataZoomComponentOption
  | GridComponentOption
  | LegendComponentOption
  | TitleComponentOption
  | ToolboxComponentOption
  | TooltipComponentOption
  | LineSeriesOption
  | PieSeriesOption
  | TreemapSeriesOption
  | BarSeriesOption
  | GaugeSeriesOption
  | HeatmapSeriesOption
>;

// 定义图表组件的属性类型
export interface MyChartProps {
  option: MyChartOption | null | undefined | any;
  width?: number | string;
  height?: number | string;
  merge?: boolean;
  loading?: boolean;
  empty?: React.ReactElement;
  style?: any;

  onClick?(event: ECElementEvent): any;
}

// 定义图表组件的引用类型
export interface MyChartRef {
  instance(): EChartsType | undefined;
}

const MyChartInner: React.ForwardRefRenderFunction<MyChartRef, MyChartProps> = (
  { option, width, height, onClick },
  ref: ForwardedRef<MyChartRef>,
) => {
  const cRef = useRef<HTMLDivElement>(null);
  const cInstance = useRef<EChartsType>();
  // 重新适配大小并开启过渡动画

  const resize = () => {
    cInstance.current?.resize({
      animation: { duration: 300 },
    });
  };
  // 初始化注册组件，监听 cRef 和 option 变化
  useEffect(() => {
    if (cRef.current) {
      // 校验 Dom 节点上是否已经挂载了 ECharts 实例，只有未挂载时才初始化
      cInstance.current = echarts.getInstanceByDom(cRef.current);
      if (!cInstance.current) {
        cInstance.current = echarts.init(cRef.current, undefined, {
          renderer: 'svg',
        });
        cInstance.current.on('click', (event) => {
          const ec = event as ECElementEvent;
          if (ec && onClick) onClick(ec);
        });
      }
      // 设置配置项
      if (option) cInstance.current?.setOption(option);
    }
  }, [cRef, option]);
  // 监听窗口大小变化重绘
  useEffect(() => {
    window.addEventListener('resize', resize);
    return () => {
      window.removeEventListener('resize', resize);
    };
  }, [option]);
  // 监听高度变化
  useLayoutEffect(() => {
    resize();
  }, [width, height]);

  // 获取实例
  const instance = () => {
    return cInstance.current;
  };
  // 对父组件暴露的方法
  useImperativeHandle(ref, () => ({
    instance,
  }));
  return <div ref={cRef} style={{ width: width, height: height }} />;
};
const EchartsDOM = React.forwardRef(MyChartInner);
export default EchartsDOM;
